﻿using DG.Tweening;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class Mian : MonoBehaviour
{
    public GameObject[] prefabs;
    public GameObject[] effects;
    public GameObject[,] objects;
    public Text text;
    public int Column;
    public int Row;
    public float Size;
    public float startTim = 1;
    public int Score;
    List<GameObject> cache = new List<GameObject>();
    // Start is called before the first frame update
    void Start()
    {
        //djfhashdfk
        objects = new GameObject[Column, Row];
        int max = prefabs.Length;
        float sx = Column * -0.5f * Size + Size * 0.5f;
        float sy = Row * -0.5f * Size + Size * 0.5f;
        for (int i = 0; i < Column; i++)
        {
            for (int j = 0; j < Row; j++)
            {
                int index = Random.Range(0, max);
                GameObject go = GameObject.Instantiate(prefabs[index]);
                go.transform.SetParent(transform);
                go.transform.localPosition = new Vector3(i * Size + sx, j * Size + sy, 0);
                Mark mark = go.AddComponent<Mark>();
                mark.Column = i;
                mark.Row = j;
                mark.Index = index;
                go.name = index.ToString();
                go.AddComponent<BoxCollider2D>();
                objects[i, j] = go;
            }
        }
    }
    
    // Update is called once per frame
    void Update()
    {
        if (startTim > 0)
        {
            startTim -= Time.deltaTime;
        }
        if (startTim < 0)
        {
            if (Input.GetMouseButtonDown(0))
            {
                lastCol = curCol;
                lastRow = curRow;
                Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
                RaycastHit2D hit = Physics2D.Raycast(ray.origin, ray.direction);
                if (hit.transform != null)
                {
                    Mark mark = hit.transform.GetComponent<Mark>();
                    curCol = mark.Column;
                    curRow = mark.Row;
                    cache.Clear();
                    Check(hit.transform.gameObject.name,mark.Column,mark.Row);
                    if (cache.Count >= 3)//3个一样的对象就销毁
                    {
                        AddScore(cache.Count);//执行加分的方法
                        PlayDestory();
                    }
                    else
                    {
                        cache.Clear();
                        Swap();
                    }
                }
            }
        }
    }
    void Check(string type,int column,int row)
    {
        if (row < 0 || row >= Row || column < 0 || column >= Column)
            return;
        GameObject go = objects[column, row];
        Debug.Log($"{GetType()}:    {go.name} {type}");
        if (go.name != type)//判断类型是否相等
            return;
        if (cache.Contains(go))//防止重复添加
            return;
        cache.Add(go);
        Check(type, column,row-1);
        Check(type, column, row + 1);
        Check(type, column - 1, row);
        Check(type, column + 1, row);
    }
    /// <summary>
    /// 销毁方法
    /// </summary>
    void PlayDestory()
    {
        float sx = Column * -0.5f * Size + Size * 0.5f;
        float sy = Row * -0.5f * Size + Size * 0.5f;
        for (int i = 0; i < cache.Count; i++)
        {
            //
            Mark mark = cache[i].GetComponent<Mark>();
            objects[mark.Column, mark.Row] = null;
            GameObject go = GameObject.Instantiate(effects[mark.Index]);
            go.transform.SetParent(transform);
            go.transform.position = new Vector3(mark.Column * Size + sx, mark.Row * Size + sy, 0);
            go.transform.localScale = new Vector3(Size, Size, Size);
            GameObject.Destroy(cache[i]);
        }
        StartCoroutine(Wait(0.6f, Fall));//0.6秒后执行
    }
    //协程
    IEnumerator Wait(float time,System.Action action)
    {
        yield return new WaitForSeconds(time);
        action();
    }
    void Fall()
    {
        float sx = Column * -0.5f * Size + Size * 0.5f;
        float sy = Row * -0.5f * Size + Size * 0.5f;
        for(int i = 0; i < Column; i++)
        {
            int count = 0;
            for(int j = 0; j < Row; j++)
            {
                if (objects[i,j] == null)
                {
                    count++;
                }
                else
                {
                    if (count > 0)
                    {
                        Mark m = objects[i,j].GetComponent<Mark>();
                        int row = j - count;
                        m.Row = row;
                        objects[i, row] = objects[i,j];
                        objects[i, row].transform.DOMove(new Vector3(i * Size + sx,row * Size + sy, 0),0.3f);
                        objects[i,j] = null;
                    }
                }
            }
        }
        Add();
    }
    void Add()
    {
        float sx = Column * -0.5f * Size + Size * 0.5f;
        float sy = Row * -0.5f * Size + Size * 0.5f;
        for(int i = 0; i < Column; i++)
        {
            for(int j = 0; j < Row; j++)
            {
                if (objects[i, j] == null)
                {
                    int max = prefabs.Length;
                    int index = Random.Range(0, max);
                    GameObject go = GameObject.Instantiate(prefabs[index]);
                    go.transform.SetParent(transform);
                    go.transform.localPosition = new Vector3(i * Size + sx, (Row+1) * Size + sy, 0);
                    go.transform.DOMove(new Vector3(i * Size + sx, j * Size + sy, 0), 0.3f);
                    Mark mark = go.AddComponent<Mark>();
                    mark.Column = i;
                    mark.Row = j;
                    mark.Index = index;
                    go.name = index.ToString();
                    go.AddComponent<BoxCollider2D>();
                    objects[i, j] = go;
                }
            }
        }
    }
    int curCol, curRow;
    int lastCol, lastRow;
    /// <summary>
    /// 交换位置的方法
    /// </summary>
    void Swap()
    {
        int ox = curCol - lastCol;
        int oy = curRow - lastRow;
        if (oy == 0||oy==-1)
        {
            if (ox == 1 || ox == -1)
            {
                SwapTest();
            }
        }else if(ox==0||ox==-1)
        {
                if (oy == 1 | oy == -1)
                {
                    SwapTest();
                }
        }
    }
    //加分
    void SwapTest()
    {
        bool fail = true;
        GameObject a = objects[curCol, curRow];
        GameObject b = objects[lastCol, lastRow];
        objects[curCol, curRow] = b;
        objects[lastCol, lastRow] = a;
        var mb = b.GetComponent<Mark>();
        mb.Column = curCol;
        mb.Row = curRow;
        var ma = a.GetComponent<Mark>();
        ma.Column = lastCol;
        ma.Row = lastRow;
        int cc = curCol;
        int cr = curRow;
        int lc = lastCol;
        int lr = lastRow;
        a.transform.DOMove(b.transform.position, 0.3f);
        b.transform.DOMove(a.transform.position, 0.3f).onComplete = () =>
        {
            cache.Clear();
            Check(b.name, cc, cr);
            int c = 0;
            if (cache.Count >= 3)
            {
                c += cache.Count;
                fail = false;
                PlayDestory();
            }
            cache.Clear();
            Check(a.name, lc, lr);
            if (cache.Count >= 3)
            {
                c += cache.Count;
                fail = false;
                PlayDestory();
            }
            cache.Clear();
            AddScore(c);
            if (fail)
            {
                objects[cc, cr] = a;
                objects[lc, lr] = b;
                a.transform.DOMove(b.transform.position, 0.3f);
                b.transform.DOMove(a.transform.position, 0.3f);
                ma.Column = cc;
                ma.Row = cr;
                mb.Column = lc;
                mb.Row = lr;
            }
        };
    }
    void AddScore(int count)
    {
        if (count < 3)
            return;
        Score += count * 100;
        count -= 3;
        Score += count * count * 10;
        text.text = Score.ToString();
    }
}
